/******************************************************************************
 * Title:     Younker Web Application Framework
 * Copyright: Copyright (c) 2004
 * Company:   YounkerSoft
 * Author: 	  Xiao Jian
 * Version:   2.0
 *****************************************************************************/
package com.younker.waf.component.dbgrid;

import java.net.*;
import java.io.*;
import java.sql.*;
import javax.servlet.*;
import javax.servlet.http.*;

import org.apache.commons.dbutils.*;
import org.apache.commons.digester.Digester;
import org.apache.commons.digester.xmlrules.DigesterLoader;
import org.apache.commons.logging.*;

import com.younker.waf.utils.WebUtil;
import com.younker.waf.db.ScrollQueryRunner;
import com.younker.waf.db.DataSourceProvider;

/**
 * DBGridServlet is the enter point of data list
 */
public class DBGridServlet extends HttpServlet
{
        static final long serialVersionUID = 1L;
        public static final String DATALIST = "datalist";
        public static final String DBGRID = "dbgrid";

        protected static DataSourceProvider dsp;
        protected DBGrids dbGrids;
        protected ServletContext ctx;

        private static final String[] urls =
        { "/component/dbgrid/dbgrid.jsp", "/component/dbgrid/dbgrid1.jsp",
                        "/component/dbgrid/dbgrid2.jsp" };
        private static final Log log = LogFactory.getLog(DBGridServlet.class);

        public void init() throws ServletException
        {
                ctx = getServletContext();
                config(ctx);
                dsp = DataSourceProvider.instance();
                info();
        }

        public void doGet(HttpServletRequest request, HttpServletResponse response)
                        throws ServletException, IOException
        {

                this.process(request, response);
        }

        public void doPost(HttpServletRequest request, HttpServletResponse response)
                        throws ServletException, IOException
        {

                this.process(request, response);
        }

        protected void config(ServletContext ctx)
        {
                try
                {
                        URL ruleURL = ctx.getResource("/WEB-INF/config/DBGridRule.xml");
                        URL gridURL = ctx.getResource("/WEB-INF/config/dbgrids.xml");
                        Digester digester = DigesterLoader.createDigester(ruleURL);
                        dbGrids = (DBGrids) digester.parse(gridURL.toString());
                } catch (Exception ex)
                {
                        log.error("load or parse the dbgrid configuration file error", ex);
                }
        }

        protected void info()
        {
                if (log.isInfoEnabled())
                        log.info("DBGrid engine initialized ");
        }

        protected void forward(DBGrid dbgrid, HttpServletRequest request,
                        HttpServletResponse response) throws ServletException, IOException
        {
                // 2009.02.14 Ф add
                if (dbgrid.getForwardURL() != null)
                        ctx.getRequestDispatcher(
                                                        dbgrid.getForwardURL()
                                                                        + generateParameter(dbgrid))
                                        .forward(request, response);
                else
                        ctx.getRequestDispatcher(
                                        urls[dbgrid.getGridType()] + generateParameter(dbgrid))
                                        .forward(request, response);
        }

        protected void process(HttpServletRequest request, HttpServletResponse response)
                        throws ServletException, IOException
        {

                DBGrid dbgrid = extractParameter(request);
                if (dbgrid == null)
                {
                        return;
                } else
                {
                        listData(dbgrid, request, response);
                }
        }

        protected String extractGridName(HttpServletRequest request, HttpSession hs)
        {
                String gridName = WebUtil.nvl(request.getParameter("dbgrid"));

                if (!gridName.equals(""))
                {
                        if (hs.getAttribute("CurrentGridName") != null)
                        {
                                hs.removeAttribute("CurrentGridName");
                        }
                        hs.setAttribute("CurrentGridName", gridName);
                }
                gridName = (String) hs.getAttribute("CurrentGridName");
                return gridName;
        }

        protected String generateParameter(DBGrid dbgrid)
        {
                StringBuffer tsb = new StringBuffer();
                tsb.append("?pages=").append(dbgrid.getPages()).append("&currpage=").append(
                                dbgrid.getCurrentPage()).append("&recnums=").append(
                                dbgrid.getRecordNum()).append("&startindex=").append(
                                dbgrid.getStartRecordNum());
                return tsb.toString();
        }

        private DBGrid extractParameter(HttpServletRequest request)
        {

                DBGrid dbgrid;
                int curpage;
                HttpSession hs = request.getSession(true);
                String isSameWhere = WebUtil.nvl(request.getParameter("samewhere"), "false");
                String page = WebUtil.nvl(request.getParameter("page"), "1");
                String orderby = request.getParameter("orderby");
                String queryType = request.getParameter("queryType");
                String gridName = extractGridName(request, hs);

                dbgrid = dbGrids.getDBGrid(gridName);
                if (dbgrid == null)
                {
                        log.error("No such dbgrid :" + gridName);
                        return null;
                }
                /**
                 * "false" means the incoming request contains a new dbgrid
                 * different with the one stored in the current session.There
                 * are two conditions: one is the new dbgrid with a different
                 * name;the other is the new dbgrid with the same name but
                 * different parameters. Both all need regenerate the
                 * "WHERE SQL",that is reparsing.
                 */
                if ("false".equals(isSameWhere))
                {
                        parseGrid(request, dbgrid);
                } else
                {
                        dbgrid.setWhereSQL(WebUtil.nvl((String) hs.getAttribute("currentWhere")));
                }

                try
                {
                        curpage = Integer.parseInt(page);
                } catch (NumberFormatException ex)
                {
                        curpage = 1;
                }
                if (queryType != null)
                        dbgrid.setGridQueryType(queryType);
                if (orderby != null)
                        dbgrid.setGridOrderBy(orderby);
                dbgrid.setCurrentPage(curpage);

                if (dbgrid.isReparse())
                        parseGrid(request, dbgrid);

                return dbgrid;
        }

        private void parseGrid(HttpServletRequest request, DBGrid dbgrid)
        {

                DBGridParser parser = new DBGridParser();
                parser.Parse(dbgrid, request);
                parser = null;
                request.getSession().setAttribute("CurrentWhere", dbgrid.getWhereSQL());
        }

        private void listData(DBGrid dbgrid, HttpServletRequest request,
                        HttpServletResponse response) throws ServletException, IOException
        {

                ResultSetHandler h = new DBGridResultSetHandler(dbgrid);
                QueryRunner run = new ScrollQueryRunner(dsp.getDataSource());

                try
                {
                        Object result = run.query(dbgrid.getSQL(), h);
                        request.setAttribute("dbgrid", dbgrid);
                        request.setAttribute("datalist", result);
                        if (log.isInfoEnabled())
                        {
                                log.info(dbgrid.getGridName() + " SQL :\n" + dbgrid.getSQL());
                        }
                } catch (SQLException ex)
                {
                        log.error(dbgrid.getGridName() + " SQL : \n" + dbgrid.getSQL());
                        log.error("Failed to generate dbgrid : " + dbgrid.getGridName(), ex);
                } finally
                {
                        forward(dbgrid, request, response);
                }
        }
}
